<template>
    <el-select v-model="state.selected"
               filterable
               clearable
               :placeholder="props.placeholder"
               @change="proxy.$emit('update:modelValue', state.selected)"
               @clear="proxy.$emit('clear')"
    >
        <el-option
                v-for="(v, i) in state.data"
                :key="i"
                :value="v[props.option.value]"
                :label="v[props.option.label]"
        />
    </el-select>
</template>

<script lang="ts" setup>
    /**
     *  下拉选择框组件
     *  @param modelValue 父组件v-model绑定值
     *  @param type 该参数为String类型，包含三个可选值："data" 、"url" 、 "dic"，默认为"data"
     *  @param params 该参数为Object类型，包含三个可选参数：url、query、data
     *  @param option 该参数为Object类型，包含两个必传参数label、value，用于定义selectOption的value与label值的key
     *  @param placeholder 提示词
     *  @description 当参数type值为"data"时，组件使用数据模式，参数params中必传参数为params.data
     *               当参数type值为"url"时，组件使用url请求获取数据，参数params中必传参数为params.url及用于定义请求条件的可选参数params.query
     *               当参数type值为"dic"时，组件使用字典模式，参数params中必传参数为字典编码params.code
     */
    import request from "/@/utils/request";
    import {Local} from "/@/utils/storage";
    import {ref, reactive, defineProps, onMounted, getCurrentInstance, watch} from "vue";

    const {proxy}: any = getCurrentInstance();

    interface Option {
        label: String,
        value: String
    }

    interface Params {
        url?: String,
        query?: Object,
        data?: Array<Option>,
        code?: String
    }

    const dataMark = "data", urlMark = "url", dicMark = "dic";

    type Type = dataMark | urlMark | dicMark;

    const props = defineProps({
        modelValue: String,
        type: {
            type: String as () => Type,
            default: "data",
        },
        params: {
            type: Object as () => Params,
            default: {},
        },
        option: {
            type: Object as () => Option,
            default: {
                label: "label",
                value: "value"
            },
        },
        placeholder: {
            type: String,
            default: "请选择",
        },
        success: {
            type: Function,
            default: () => {
            },
        },
    });

    const state = reactive({
        data: Array as () => Array<Option>,
        selected: "",
        dictionaryAllData: []
    });

    const _init = () => {
        if (_validationParameter()) {
            switch (props.type) {
                case dataMark:
                    _getDataForProps();
                    break;
                case urlMark:
                    _getDataForUrl();
                    break;
                case dicMark:
                    _getDataForDic();
                    break;
            }
        } else {
            console.error("请检查组件参数！");
        }
    };

    /**
     *  组件参数验证
     *  @return 类型：Boolean，验证通过返回true，反之返回false
     */
    const _validationParameter = (): Boolean => {
        let result: Boolean = true;
        /*if (_isEmpty(props.option.label) || _isEmpty(props.option.value)) {
            result = false;
        }*/
        if (props.type == dataMark && _isEmpty(props.params.data)) {
            result = false;
        }
        if (props.type == urlMark && _isEmpty(props.params.url)) {
            result = false;
        }
        if (props.type == dicMark && _isEmpty(props.params.code)) {
            result = false;
        }
        return result;
    }

    /**
     *  根据字典获取数据
     */
    const _getDataForDic = () => {
        state.dictionaryAllData = Local.get("dictionaryData");
        if (state.dictionaryAllData == null) {
            request({
                url: "/api/system/dictionary/content/data/modelMap",
                method: "get",
                params: {},
            })
                .then((res) => {
                    if (res.data.version) {
                        Local.set("dictionaryData", res.data.data);
                        state.dictionaryAllData = res.data.data;
                        setTimeout(() => {
                            initDicSelect();
                        }, 100);
                    }
                })
                .catch((error) => {
                    proxy.$wigem.log("字典接口异常");
                });
        } else {
            setTimeout(() => {
                initDicSelect();
            }, 100);
        }
    }
    const initDicSelect = () => {
        let data: Object = state.dictionaryAllData[props.params.code];
        let dicArr: Array<Option> = [];
        for (let key in data) {
            let option: Option = {
                label: data[key].text,
                value: data[key].value
            }
            dicArr.push(option);
        }
        state.data = dicArr;
    }

    /**
     *  从父组件获取数据
     */
    const _getDataForProps = () => {
        state.data = props.params.data;
        state.selected = props.modelValue;
    }

    /**
     *  根据url请求获取数据
     */
    const _getDataForUrl = async () => {
        let res: any = await request({
            url: props.params.url,
            method: "get",
            params: props.params.query
        });
        if (res.success) {
            state.data = res.data;
            props.success(state.data);
        }
    };

    onMounted(() => {
        _init();
    });

    /**
     *  非空验证
     */
    const _isEmpty = (value: any) => {
        if (value === '' || value == null || value == undefined) {
            return true
        }
        return false
    }
</script>
